package cn.minsh.lims.eoms.modules.app.service.impl;

import cn.minsh.lims.eoms.common.exception.RRException;
import cn.minsh.lims.eoms.common.utils.DateUtils;
import cn.minsh.lims.eoms.common.utils.ObjectToMapUtils;
import cn.minsh.lims.eoms.common.utils.PageUtils;
import cn.minsh.lims.eoms.common.utils.Query;
import cn.minsh.lims.eoms.modules.app.controller.req.MaintenancePlanListReq;
import cn.minsh.lims.eoms.modules.app.controller.req.MaintenancePlanReq;
import cn.minsh.lims.eoms.modules.app.controller.res.MaintenancePlanListRes;
import cn.minsh.lims.eoms.modules.app.dao.MaintenancePlanDao;
import cn.minsh.lims.eoms.modules.app.entity.MaintenancePlanEntity;
import cn.minsh.lims.eoms.modules.app.entity.PlanContentEntity;
import cn.minsh.lims.eoms.modules.app.entity.PlanRemindEntity;
import cn.minsh.lims.eoms.modules.app.entity.PlanScopeEntity;
import cn.minsh.lims.eoms.modules.app.enums.BusiTypeEnum;
import cn.minsh.lims.eoms.modules.app.enums.FrequencyEnum;
import cn.minsh.lims.eoms.modules.app.enums.PlanStatusEnum;
import cn.minsh.lims.eoms.modules.app.service.MaintenancePlanService;
import cn.minsh.lims.eoms.modules.app.service.PlanContentService;
import cn.minsh.lims.eoms.modules.app.service.PlanRemindService;
import cn.minsh.lims.eoms.modules.app.service.PlanScopeService;
import cn.minsh.lims.eoms.modules.app.utils.LocalDateUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.bytebuddy.asm.Advice;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author Administrator
 */
@Service("maintenancePlanService")
public class MaintenancePlanServiceImpl extends ServiceImpl<MaintenancePlanDao, MaintenancePlanEntity> implements MaintenancePlanService {

    @Autowired
    private PlanScopeService planScopeService ;
    @Autowired
    private PlanContentService planContentService ;
    @Autowired
    private PlanRemindService planRemindService ;

    @Override
    public PageUtils queryPage(Map<String, Object> params,Long userId) {
        IPage<MaintenancePlanEntity> page = this.page(
                new Query<MaintenancePlanEntity>().getPage(params),
                new QueryWrapper<MaintenancePlanEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePlan(MaintenancePlanReq req,Long userId) {

        if (req.getFirstPlanDate() != null && req.getInvalidTime() != null && req.getFirstPlanDate().after(req.getInvalidTime())){
            throw new RRException("首次保养时间不能晚于失效时间") ;
        }

        //添加保养计划
        MaintenancePlanEntity planEntity = new MaintenancePlanEntity() ;
        BeanUtils.copyProperties(req,planEntity);
        planEntity.setCreateBy(userId);
        planEntity.setCreateTime(new Date());
        planEntity.setUpdateBy(userId);
        planEntity.setUpdateTime(new Date());
        try {
            Integer dayCount = LocalDateUtils.getDayCount(new Date(), planEntity.getFirstPlanDate());
            if (planEntity.getInvalidTime() != null) {
                Integer endCount = LocalDateUtils.getDayCount(new Date(), planEntity.getInvalidTime());
                if (dayCount >= 0 && endCount < 0) {
                    planEntity.setStatus(PlanStatusEnum.STARTED.getCode());
                } else if (dayCount < 0) {
                    planEntity.setStatus(PlanStatusEnum.NOT_STARTED.getCode());
                } else if (endCount > 0) {
                    planEntity.setStatus(PlanStatusEnum.OVER.getCode());
                }
            } else {
                if (dayCount >= 0) {
                    planEntity.setStatus(PlanStatusEnum.STARTED.getCode());
                } else {
                    planEntity.setStatus(PlanStatusEnum.NOT_STARTED.getCode());
                }
            }
        }catch (Exception parseException){
            parseException.printStackTrace();
        }
        this.save(planEntity) ;

        Long planId = planEntity.getId() ;

        //TODO 添加保养时间
        //3、添加巡检提醒
        if (!CollectionUtils.isEmpty(req.getRemind())) {
            List<PlanRemindEntity> remindEntities = new ArrayList<>();
            req.getRemind().stream().forEach(e -> {
                PlanRemindEntity remindEntity = new PlanRemindEntity();
                remindEntity.setLeadTime(e);
                remindEntity.setPlanId(planId);
                remindEntity.setIsDel(0);
                remindEntity.setType(BusiTypeEnum.MAINTENANCEPLAN.getCode());
                remindEntities.add(remindEntity);
            });
            planRemindService.saveBatch(remindEntities);
        }
        //添加保养范围
        List<PlanScopeEntity> scopeEntityList = new ArrayList<>() ;
        List<Long> scopeList = req.getScopeIdList() ;
        scopeList.stream().forEach(e->{
            PlanScopeEntity planScopeEntity = new PlanScopeEntity() ;
            planScopeEntity.setPlanId(planId);
            planScopeEntity.setScopeId(e);
            planScopeEntity.setType(BusiTypeEnum.MAINTENANCEPLAN.getCode());
            scopeEntityList.add(planScopeEntity) ;
        });
        planScopeService.saveBatch(scopeEntityList) ;
        //添加保养内容
        List<PlanContentEntity> planContentEntityList = new ArrayList<>() ;
        req.getContentList().stream().forEach(p->{
            PlanContentEntity planContentEntity = new PlanContentEntity() ;
            planContentEntity.setPlanId(planId);
            planContentEntity.setContent(p);
            planContentEntity.setType(BusiTypeEnum.MAINTENANCEPLAN.getCode());
            planContentEntityList.add(planContentEntity) ;
        });
        planContentService.saveBatch(planContentEntityList) ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePlanById(MaintenancePlanReq req,Long userId) {
        //查询记录号

        if (req.getFirstPlanDate() != null && req.getInvalidTime() != null && req.getFirstPlanDate().after(req.getInvalidTime())){
            throw new RRException("首次保养时间不能晚于失效时间") ;
        }

        MaintenancePlanEntity planEntity = this.getById(req.getId()) ;
        if (Objects.isNull(planEntity) || planEntity.getId() == null){
            throw new RRException("保养计划记录不存在") ;
        }
        if (StringUtils.isNotBlank(req.getName())) {
            planEntity.setName(req.getName());
        }
        if (req.getLevel()!=null) {
            planEntity.setLevel(req.getLevel());
        }
        if (req.getFirstPlanDate() != null) {
            planEntity.setFirstPlanDate(req.getFirstPlanDate());
        }
        if (req.getFrequency()!=null) {
            planEntity.setFrequency(req.getFrequency());
        }
        if (req.getAgentId()!=null) {
            planEntity.setAgentId(req.getAgentId());
        }
        if (req.getInvalidTime()!=null) {
            planEntity.setInvalidTime(req.getInvalidTime());
        }else{
            planEntity.setInvalidTime(null);
        }
        planEntity.setUpdateBy(userId);
        planEntity.setUpdateTime(new Date());

        //判断首次保养时间和当前时间比较
        try {
            Integer dayCount = LocalDateUtils.getDayCount(new Date(),planEntity.getFirstPlanDate()) ;
            if (planEntity.getInvalidTime()!= null){
                Integer endCount = LocalDateUtils.getDayCount(new Date(),planEntity.getInvalidTime()) ;
                if (dayCount>=0 && endCount<0){
                    planEntity.setStatus(PlanStatusEnum.STARTED.getCode());
                }else if(dayCount<0){
                    planEntity.setStatus(PlanStatusEnum.NOT_STARTED.getCode());
                }else if(endCount>0){
                    planEntity.setStatus(PlanStatusEnum.OVER.getCode());
                }
            }else{
                if (dayCount >= 0) {
                    planEntity.setStatus(PlanStatusEnum.STARTED.getCode());
                }else{
                    planEntity.setStatus(PlanStatusEnum.NOT_STARTED.getCode());
                }
            }

        } catch (ParseException parseException) {
            parseException.printStackTrace();
        }

        //更新记录
        this.updateById(planEntity) ;

        //TODO 修改保养时间
        //3、添加巡检提醒
        //3.1、删除提醒时间
        planRemindService.deleteByPlanId(BusiTypeEnum.MAINTENANCEPLAN.getCode(),planEntity.getId()); ;
        //3.2、添加提醒时间
        List<PlanRemindEntity> remindEntities = new ArrayList<>();
        req.getRemind().stream().forEach(e->{
            PlanRemindEntity remindEntity = new PlanRemindEntity() ;
            remindEntity.setPlanId(planEntity.getId());
            remindEntity.setIsDel(0);
            remindEntity.setType(BusiTypeEnum.MAINTENANCEPLAN.getCode());
            remindEntity.setLeadTime(e);
            remindEntities.add(remindEntity) ;
        });
        planRemindService.saveBatch(remindEntities);


        //删除范围
        planScopeService.deleteByPlanId(BusiTypeEnum.MAINTENANCEPLAN.getCode(),planEntity.getId());
        //添加范围
        List<PlanScopeEntity> scopeEntityList = new ArrayList<>() ;
        List<Long> scopeList = req.getScopeIdList() ;
        scopeList.stream().forEach(e->{
            PlanScopeEntity planScopeEntity = new PlanScopeEntity() ;
            planScopeEntity.setPlanId(planEntity.getId());
            planScopeEntity.setScopeId(e);
            planScopeEntity.setType(BusiTypeEnum.MAINTENANCEPLAN.getCode());
            scopeEntityList.add(planScopeEntity) ;
        });
        planScopeService.saveBatch(scopeEntityList) ;
        //删除内容
        planContentService.deleteByPlanId(BusiTypeEnum.MAINTENANCEPLAN.getCode(),planEntity.getId()) ;
        //添加内容
        List<PlanContentEntity> planContentEntityList = new ArrayList<>() ;
        req.getContentList().stream().forEach(p->{
            PlanContentEntity planContentEntity = new PlanContentEntity() ;
            planContentEntity.setPlanId(planEntity.getId());
            planContentEntity.setContent(p);
            planContentEntity.setType(BusiTypeEnum.MAINTENANCEPLAN.getCode());
            planContentEntityList.add(planContentEntity) ;
        });
        planContentService.saveBatch(planContentEntityList) ;
    }

    @Override
    public PageUtils queryListPage(MaintenancePlanListReq req,Long userId) {

        QueryWrapper<MaintenancePlanEntity> wrapper = new QueryWrapper<>() ;

        if (req.getStatus()!= null){
            wrapper.eq("status",req.getStatus()) ;
        }
        if (!CollectionUtils.isEmpty(req.getScopeIdList())){
            //根据范围id列表查询计划id列表
            QueryWrapper<PlanScopeEntity> planScopeEntityQueryWrapper = new QueryWrapper<>() ;
            planScopeEntityQueryWrapper.eq("type",BusiTypeEnum.MAINTENANCEPLAN.getCode()) ;
            planScopeEntityQueryWrapper.in("scope_id",req.getScopeIdList()) ;
            List<PlanScopeEntity> scopeList = planScopeService.list(planScopeEntityQueryWrapper) ;
            if (!CollectionUtils.isEmpty(scopeList)){
                List<Long> planIdList = new ArrayList<>() ;
                scopeList.stream().forEach(e->{
                    if (planIdList.indexOf(e.getPlanId())==-1){
                        planIdList.add(e.getPlanId()) ;
                    }
                });
                if (!CollectionUtils.isEmpty(planIdList)){
                    wrapper.in("id",planIdList) ;
                }
            }
        }
        if (StringUtils.isNotBlank(req.getName())){
            wrapper.like("name","%"+req.getName()+"%") ;
        }
        if (!CollectionUtils.isEmpty(req.getCreateByList())){
            wrapper.in("create_by",req.getCreateByList()) ;
        }
        if (!CollectionUtils.isEmpty(req.getAgentIdList())){
            wrapper.in("agent_id",req.getAgentIdList()) ;
        }
        wrapper.eq("is_del",0);
        if (StringUtils.isNotBlank(req.getOrder()) && StringUtils.isNotBlank(req.getSort())){
            wrapper.orderBy(StringUtils.isNotBlank(req.getOrder()) && StringUtils.isNotBlank(req.getSort()),"asc".equals(req.getSort().toLowerCase()),req.getOrder()) ;
        }else{
            wrapper.orderByDesc("id") ;
        }

        IPage<MaintenancePlanEntity> page = this.page(
                new Query<MaintenancePlanEntity>().getPage(ObjectToMapUtils.setConditionMap(req)),
                wrapper
        );

        IPage<MaintenancePlanListRes> retPage = new Page<>(page.getCurrent(),page.getSize()) ;
        retPage.setPages(page.getPages()) ;
        retPage.setTotal(page.getTotal()) ;

        List<MaintenancePlanListRes> retList = new ArrayList<>() ;
        if (!CollectionUtils.isEmpty(page.getRecords())){
            QueryWrapper<PlanScopeEntity> planScopeEntityQueryWrapper = new QueryWrapper<>() ;
            planScopeEntityQueryWrapper.eq("type",BusiTypeEnum.MAINTENANCEPLAN.getCode()) ;
            List<PlanScopeEntity> scopeList = planScopeService.list(planScopeEntityQueryWrapper) ;

            page.getRecords().stream().forEach(e->{
                MaintenancePlanListRes res = new MaintenancePlanListRes() ;
                BeanUtils.copyProperties(e,res);
                //计算首次保养时间
                if (e.getFirstPlanDate()!=null) {
                    String firstDateStr = DateUtils.format(e.getFirstPlanDate(), DateUtils.DATE_PATTERN);
                    if (FrequencyEnum.WEEK.getCode().equals(e.getFrequency())) {
                        //计算首次日期是星期几
                        firstDateStr += "(" + LocalDateUtils.getWeekNameOfDate(e.getFirstPlanDate()) + ")";
                    }
                    res.setFirstDateStr(firstDateStr);
                }
                if (!CollectionUtils.isEmpty(scopeList)){
                    res.setScopeIdList(scopeList.stream().filter(pp->pp.getPlanId().equals(e.getId())).map(PlanScopeEntity::getScopeId).collect(Collectors.toList()));
                }
                retList.add(res) ;
            });
        }
        retPage.setRecords(retList) ;
        return new PageUtils(retPage);
    }

    @Override
    public MaintenancePlanListRes queryPlanById(Long id,Long userId) {

        MaintenancePlanListRes res = new MaintenancePlanListRes() ;
        MaintenancePlanEntity planEntity = this.getById(id) ;
        if (planEntity==null ||planEntity.getId() == null){
            throw new RRException("记录不存在") ;
        }
        BeanUtils.copyProperties(planEntity,res);
        //计算首次保养时间
        String firstDateStr = DateUtils.format(planEntity.getFirstPlanDate(),DateUtils.DATE_PATTERN) ;
        if (FrequencyEnum.WEEK.getCode().equals(planEntity.getFrequency())){
            //计算首次日期是星期几
            firstDateStr+="("+LocalDateUtils.getWeekNameOfDate(planEntity.getFirstPlanDate())+")" ;
        }
        res.setFirstDateStr(firstDateStr);

        //获取范围
        QueryWrapper<PlanScopeEntity> planScopeEntityQueryWrapper = new QueryWrapper<>() ;
        planScopeEntityQueryWrapper.eq("plan_id",id) ;
        planScopeEntityQueryWrapper.eq("type",BusiTypeEnum.MAINTENANCEPLAN.getCode()) ;
        List<PlanScopeEntity> scopeList = planScopeService.list(planScopeEntityQueryWrapper) ;

        if (!CollectionUtils.isEmpty(scopeList)){
            res.setScopeIdList(scopeList.stream().map(PlanScopeEntity::getScopeId).collect(Collectors.toList()));
        }
        //获取内容
        QueryWrapper<PlanContentEntity> planContentEntityQueryWrapper = new QueryWrapper<>() ;
        planContentEntityQueryWrapper.eq("plan_id",id) ;
        planContentEntityQueryWrapper.eq("type",BusiTypeEnum.MAINTENANCEPLAN.getCode()) ;
        List<PlanContentEntity> contentEntityList = planContentService.list(planContentEntityQueryWrapper) ;
        if (!CollectionUtils.isEmpty(contentEntityList)) {
            res.setContentList(contentEntityList.stream().map(PlanContentEntity::getContent).collect(Collectors.toList()));
        }

        //提醒列表
        List<PlanRemindEntity> planRemindEntityList = planRemindService.listByTypeAndPlanId(BusiTypeEnum.MAINTENANCEPLAN.getCode(),id) ;
        if (!CollectionUtils.isEmpty(planRemindEntityList)){
            res.setRemindList(planRemindEntityList.stream().map(PlanRemindEntity::getLeadTime).collect(Collectors.toList()));
        }
        return res;
    }

}